using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Framework.Remoting.Client;
using Framework.Remoting.Conventions;
using Framework.Tests.Wcf.Client.ServiceDefinition;
using Microsoft.Practices.Unity;
using Rhino.Mocks;
using Xunit;

namespace Framework.Tests.Wcf.Client
{
    public abstract class ManagedChannelManagerTestBase<T>
        where T : RequestBase
    {
        protected readonly IRequest Target;
        private readonly IUnityContainer unityContainer = new UnityContainer();
        protected readonly MockRepository MockRepository = new MockRepository();
        protected readonly WcfServiceInfo WcfServiceInfo;

        protected ManagedChannelManagerTestBase()
        {
            ChannelContractMock = MockRepository.StrictMock<IChannelContractMock>();
            channelFactoryFactoryMock = MockRepository.StrictMock<IChannelFactoryFactory>();
            channelFactoryMock = MockRepository.StrictMock<IChannelFactory<IContract>>();

            unityContainer.RegisterInstance(ChannelContractMock);
            unityContainer.RegisterInstance(channelFactoryFactoryMock);
            unityContainer.RegisterInstance(channelFactoryMock);

            Target = unityContainer.Resolve<T>();
            
            WcfServiceInfo = new WcfServiceInfo(new NetTcpBinding(), new Uri("net.tcp://pouet.org"));
        }

        protected readonly IChannelContractMock ChannelContractMock;

        private readonly IChannelFactoryFactory channelFactoryFactoryMock;

        private readonly IChannelFactory<IContract> channelFactoryMock;

        [Fact]
        public void Test_BeginRequest_Succeed()
        {
            MockBeginRequest();

            MockRepository.ReplayAll();
            Target.BeginRequest<IContract>(WcfServiceInfo);
            MockRepository.VerifyAll();
        }

        protected void MockBeginRequest(CommunicationState communicationState)
        {
            MockBeginRequest();

            ChannelContractMock.Expect(x => x.State).Return(communicationState);
        }

        protected void MockBeginRequest()
        {
            channelFactoryFactoryMock
                .Expect(x => x.Create<IContract>(WcfServiceInfo))
                .Return(channelFactoryMock);

            channelFactoryMock
                .Expect(x => x.CreateChannel(new EndpointAddress(WcfServiceInfo.Uri)))
                .Return(ChannelContractMock);
        }

        [Fact]
        public void When_communication_state_is_closed_then_do_not_close()
        {
            ChannelContractMock.Expect(x => x.State).Return(CommunicationState.Closed);
            MockRepository.ReplayAll();
            Target.EndRequest(ChannelContractMock);
            MockRepository.VerifyAll();
        }

        [Fact]
        public void When_communication_state_is_faulted_then_abort()
        {
            ChannelContractMock.Expect(x => x.State).Return(CommunicationState.Faulted).Repeat.Any();
            ChannelContractMock.Expect(x => x.Abort());
            MockRepository.ReplayAll();
            Target.EndRequest(ChannelContractMock);
            MockRepository.VerifyAll();
        }
    }
}